<?php
require_once ('simplepie.inc.php');

define('ROOT_PATH',realpath('./')); //Path to root directory of the site.
define('CACHE_DURATION', 3600); // RSS Feeds are stored in cache. This parameter shows how long they still valid and don't need to be updated(in seconds).
define('FEED_CACHE_PATH', './rss-cache'); // RSS cache directory(script must have write permissions to this directory)
define('IMAGE_CACHE_PATH', './image-cache'); // Generated twictures cache directory(script must have write permissions to this directory). Note: directory must be inside document root, you will not se images otherwise.
define('SHORT_TAGS_FILE', 'db.sqlite'); // Twictures has option to generate shortened urls. All data about which template and feed matches given short url is stored in file saved by path provided in this parameter. (File must be writable by script)
define('CLEAR_CACHE_SECRET', 'zzzaaa'); //Secret word for clearing a cache, change it to non-default value.
$CLEAR_CACHE_IP_FILTER = array('127.0.0.1'); //List of IP addresses which have permission to clear cache(correct secret word still required for this IPs)
define('ENABLE_APC', True); // Enable APC(Alternative PHP Cache) in-memory caching for rss feeds(APC must be installed and configured properly)

define('COUNT_REQUEST_ERROR', 3); // Number of non-successful attempts to get a response from the server, after which there is a timeout 
define('TIMEOUT_REQUEST', 60); // Duration of the timeout in seconds 

//You may need to restrict access for some templates or RSS feeds. This two variables will help you. Just provide a list of all unwanted template IDs and feed URLs. You can also fill this arrays programmaticaly from file or DB etc. 
$RESTRICTED_TEMPLATES = array(); //List of restricted template ids(strings)
$RESTRICTED_FEEDS = array(); //List of restricted feed urls(strings)


// Gets data from url with curl

function get_data_from_url($url, $is_post = False, $post_data = array()) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 60 sec
    curl_setopt($ch, CURLOPT_POST, $is_post);
    if ($is_post) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }

    $response = curl_exec($ch);
    $result = array();
    $result['http_status'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $result['response'] = $response;
    $result['content_type'] = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    $result['last_url'] = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    return $result;
}

// Get image cache file name

function get_image_cache_file_name($template_id, $rss_feed, $text, $image_size) {
    $result = IMAGE_CACHE_PATH . '/' . $template_id . '/' . md5($rss_feed);
    if ($image_size) {
        $result.= '/' . $image_size;
    }
    $file_name = md5($text);
    $result.= '/' . $file_name;
    return $result;
}

//Unlinks outdated files and saves image to local directory

function save_image_to_cache($image, $file_name) {
    $dir = substr($file_name, 0, strrpos($file_name, '/'));
    if (!file_exists($dir)) {
        mkdir($dir, 0755, True);
    }
    $old_files=glob($dir.'/*.*');
    foreach($old_files as $file) {
        unlink($file);
    }
    $fh = fopen($file_name, 'w');
    fwrite($fh, $image['response']);
    fclose($fh);
}

// Try to get image from cache or return false if none

function get_image_from_cache($file_name) {
    $file = glob($file_name . ".*");
    if(!count($file)) {
        return false;
    }
    else {
        return $file[0];
    }
}

//Gets last successfuly downloaded image from given directory

function get_last_known_image($file_name) {
    $dir = dirname($file_name . '.ext');
    $file = glob($dir . "/*.*");
    if(!count($file)) {
        return false;
    }
    else {
        return $file[0];
    }
}

// Set short tag information

function set_short_tag() {
    $template_id = (isset($_GET['template_id']) and strlen($_GET['template_id'])) ? $_GET['template_id'] : die('Missing required argument template_id');
    $rss_feed = (isset($_GET['rss_feed']) and strlen($_GET['rss_feed'])) ? $_GET['rss_feed'] : die('Missing required argument rss_feed');
    $rss_feed = trim(strtolower($rss_feed));
    $image_size = isset($_GET['size']) ? $_GET['size'] : 'false';
    $id = md5($template_id.$rss_feed.$image_size);
    
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $query = $db->query("SELECT * FROM shorttags WHERE id = '{$id}'");
    $result = $query->current();

    if (! $result) {// not record
        $result = create_short_tag($id, $template_id, $rss_feed, $image_size);
    }
    
    return $result;
}

// Create and return short URL key

function create_short_tag($id, $template_id, $rss_feed, $image_size) {
    $timeout_request = time();
    //get 7 character short tag
    $short_key = substr($id, 0, 7);    
    
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    //protection against sql injection
    $sql = sprintf("
            REPLACE INTO shorttags (id, short_key, template_id, rss_feed, image_size, is_request, count_request, timeout_request) 
            VALUES ('{$id}', '{$short_key}', '%s', '%s', '%s', 'false', '0', '{$timeout_request}');
        ",
        sqlite_escape_string($template_id), 
        sqlite_escape_string($rss_feed),
        sqlite_escape_string($image_size)
    );
    
    $result = $db->queryExec($sql);
    $query = $db->query("SELECT * FROM shorttags WHERE id = '{$id}'");
    $result = $query->current();
    return $result;
}

// Get short tag information

function get_short_tag_info() {
    $short_key = strtolower($_GET['st']);    
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $query = $db->query("SELECT * FROM shorttags WHERE short_key = '{$short_key}'");
    $result = $query->current();
    
    if (! $result) {
        die("Short tag with given id not found");
    }        
    return $result;   
}

// Protects the connection from another request

function protection_request($id, $is_request) {
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $sql = "UPDATE shorttags SET is_request = '{$is_request}' WHERE id = '{$id}'";
    $result = $db->queryExec($sql);
}

// Increment in unsuccessful attempts to counter

function update_counter_requests($id, $count_request) {
    $count_request++;
    $timeout_request = time();
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $sql = "UPDATE shorttags SET count_request = '{$count_request}', timeout_request = '{$timeout_request}' WHERE id = '{$id}'";
    $result = $db->queryExec($sql);
}

// Reset the error count query

function reset_request($id) {
    $timeout_request = time();
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $sql = "UPDATE shorttags SET count_request = '0', timeout_request = '{$timeout_request}' WHERE id = '{$id}'";
    $result = $db->queryExec($sql);
}

// Recursively unlink directories

function delTree($dir) {
    $files = glob( $dir . '*', GLOB_MARK );
    foreach( $files as $file ) {
        if( is_dir( $file ) )
            delTree( $file );
        else
            unlink( $file );
    }

    if (is_dir($dir)) rmdir( $dir );

}

// BEGIN
if (!file_exists(FEED_CACHE_PATH)) {
    mkdir(FEED_CACHE_PATH,0755) or die ("Failed to create Feed cache directory. Check permissions or create it manually");
}
elseif (!is_writable(FEED_CACHE_PATH)) {
    die("Feed cache directory is not writable");
}

if (!file_exists(IMAGE_CACHE_PATH)) {
    mkdir(IMAGE_CACHE_PATH,0755) or die("Failed to create Image cache directory. Check permissions or create it manually");
}
elseif (!is_writable(IMAGE_CACHE_PATH)) {
    die("Image cache directory is not writable");
}

if (!file_exists(SHORT_TAGS_FILE)) {
    $db = new SQLiteDatabase(SHORT_TAGS_FILE);
    $result = $db->queryExec('CREATE TABLE "shorttags" ("id" VARCHAR(255) PRIMARY KEY NOT NULL, "short_key" VARCHAR(10), "template_id" VARCHAR(255), "rss_feed" TEXT, "image_size" VARCHAR(255) DEFAULT "false", "is_request" BOOLEAN DEFAULT "false", "count_request" INTEGER(5) DEFAULT 0, "timeout_request" INTEGER)');
}

if (isset($_GET['clear_cache'])) {
    if (!in_array($_SERVER['REMOTE_ADDR'], $CLEAR_CACHE_IP_FILTER)){
        die("You do not have permission to clear cache");
    }
    if ($_GET['clear_cache'] == CLEAR_CACHE_SECRET) {
        delTree(FEED_CACHE_PATH);
        delTree(IMAGE_CACHE_PATH);
        exit('Cache cleared!');
    }
    else {
        die("Wrong secret");
    }
}

if (isset($_GET['st'])) {
    $info = get_short_tag_info();    
} else {
    $info = set_short_tag();
}

if (array_search($info['template_id'], $RESTRICTED_TEMPLATES) !== False) {
    die("You can not use template ".$info['template_id']);
}

if (array_search($info['rss_feed'], $RESTRICTED_FEEDS) !== False) {
    die("You can not use feed ".$info['rss_feed']);
}

if(ENABLE_APC and function_exists('apc_fetch')){
    $text=apc_fetch('twictures_rss_'.md5($info['rss_feed']));
}
if(!isset($text) or !$text){
    $feed = new SimplePie($info['rss_feed'], FEED_CACHE_PATH);
    $feed->set_cache_duration(CACHE_DURATION);
    $success = $feed->init();

    if (!$success) {
        die("Failed to load feed");
    }

    $feed->handle_content_type();
    $feed_items = $feed->get_items();
    $text = $feed_items[0];
    $text = $text->get_content();
    if(ENABLE_APC and function_exists('apc_store')){
        apc_store('twictures_rss_'.md5($info['rss_feed']), $text, CACHE_DURATION);
    }
}

$image_cache_file = get_image_cache_file_name($info['template_id'], $info['rss_feed'], $text, $info['image_size']);
$last_known_image = get_last_known_image($image_cache_file);
$image = get_image_from_cache($image_cache_file);

if (! $image) {//not image
    if ($info['is_request'] == 'true') {//such a request is processed by the server
        die("Failed to load image. Please try later");
    } else {
        $is_count_request = ($info['count_request'] > COUNT_REQUEST_ERROR); // limit on attempts
        $is_timeout_request = ((time() - $info['timeout_request']) < TIMEOUT_REQUEST); // limit time
        if($is_count_request  && $is_timeout_request) {
            die("Failed to load image. Please try later");
        }
    }

    protection_request($info['id'], 'true');
    
    $ecard_api_url = "http://zetaprints.com/?page=template-preview-ecard;TemplateID=" . $info['template_id'];
    $image_size = explode("x", $info['image_size']);
    if ( count($image_size) == 2 ) {
        $ecard_api_url.= ";Width=$image_size[0];Height=$image_size[1]";
    }

    $ecard_api_response = get_data_from_url($ecard_api_url, True, array('_1' => $text));
    $ecard_api_response = $ecard_api_response['response'];
    
    protection_request($info['id'], 'false');
    
    if (strpos($ecard_api_response, "Invalid TemplateID.") !== False) {
        if($last_known_image){
            $image = $last_known_image;
        }
        else{
        	update_counter_requests($info['id'], $info['count_request']);
            die("Invalid TemplateID.");
        }
    }
    else{
        $thumb_url = $ecard_api_response;
        $image = get_data_from_url($thumb_url);
        if ($image['http_status'] == 200 and substr($image['content_type'], 0, 5) == "image") {
            $ext = '.' . end(explode('.', $image['last_url']));
            save_image_to_cache($image, $image_cache_file . $ext);
            $image = $image_cache_file . $ext;
            reset_request($info['id']);
        }
        elseif($last_known_image) {
            $image = $last_known_image;
        }
        else {
            update_counter_requests($info['id'], $info['count_request']);
            die("Failed to load image. Please try later");
        }
    }
}

$server = isset($_SERVER['HTTPS']) ? "https://" : "http://".$_SERVER['HTTP_HOST'];
$get_shorttag = isset($_GET['get_shorttag']) ? $_GET['get_shorttag'] : 0;
if ($get_shorttag) {
    print $server.$_SERVER['PHP_SELF']."?st=".$info['short_key'];
}
else {
    $image = realpath($image);
    $root = str_replace("\\","/",ROOT_PATH);
    $image = str_replace("\\","/",$image);
    header("Location: ".$server.str_replace($root, '', $image), True, 307);
}
